// // Copyright (c) 2009 All Right Reserved // // vl // // 2009-01-01 // Contains ... using System; using System.Diagnostics.Contracts; using System.Globalization; using System.Text; using System.Xml.Linq; using System.Xml.Serialization; using LargoCommon.Abstract; namespace LargoCommon.Music { /// Bit Range. /// /// BitRange represents interval of bits inside of binary structure. [Serializable] [XmlRoot] public sealed class BitRange : ICloneable, IComparable { #region Constructors /// Initializes a new instance of the BitRange class. Serializable. public BitRange() { } /// Initializes a new instance of the BitRange class. /// Order of system. /// Starting bit. /// Length of the range. public BitRange(byte order, byte givenBitFrom, byte length) { //// Contract.Requires(order > 0); //// This all code is bit slow and very often used - any guess how to improve it? if (order == 0) { throw new ArgumentException("Order of bit range must not be 0."); } this.Order = order; this.BitFrom = givenBitFrom; if (length > 0) { int bitTo; checked { bitTo = this.BitFrom + length - 1; if (bitTo < 0) { bitTo = 0; } if (bitTo > order - 1) { bitTo = order - 1; } } this.BitTo = (byte)bitTo; //// this.BitTo = (byte)Math.Max(this.BitFrom + length - 1, 0); //// this.BitTo = (byte)Math.Min(this.BitTo, this.Order - 1); this.Length = (byte)(this.BitTo - this.BitFrom + 1); } else { this.BitTo = 0; this.Length = 0; } } #endregion #region Properties - Xml /// Gets Xml representation. /// Property description. public XElement GetXElement { get { //// Contract.Requires(this.BitRange != null); var xmlBitRange = new XElement( "B", new XAttribute("Order", this.Order), new XAttribute("Start", this.BitFrom), new XAttribute("Length", this.Length)); return xmlBitRange; } } #endregion #region Properties /// Gets or sets order of system. /// Property description. public byte Order { get; set; } /// Gets or sets the first bit of the range. /// Property description. public byte BitFrom { get; set; } /// Gets or sets length of the range. /// Property description. public byte Length { get; set; } /// Gets a value indicating whether IsEmpty. /// Property description. public bool IsEmpty => this.Length <= 0; /// Gets or sets the last bit of the range. /// Property description. [XmlIgnore] public byte BitTo { get; set; } #endregion #region Static operators //// TICS rule 7@526: Reference types should not override the equality operator (==) //// public static bool operator ==(BitRange range1, BitRange range2) { return object.Equals(range1, range2); } //// public static bool operator !=(BitRange range1, BitRange range2) { return !object.Equals(range1, range2); } //// but TICS rule 7@530: Class implements interface 'IComparable' but does not implement '==' and '!='. /// /// Implements the operator <. /// /// The object1. /// The object2. /// /// Returns value. /// public static bool operator <(BitRange object1, BitRange object2) { if (object1 != null && object2 != null) { return object1.BitFrom < object2.BitFrom; } return false; } /// /// Implements the operator >. /// /// The object1. /// The object2. /// /// Returns value. /// public static bool operator >(BitRange object1, BitRange object2) { if (object1 != null && object2 != null) { return object1.BitFrom > object2.BitFrom; } return false; } /// /// Implements the operator <=. /// /// The object1. /// The object2. /// /// Returns value. /// public static bool operator <=(BitRange object1, BitRange object2) { if (object1 != null && object2 != null) { return object1.BitFrom <= object2.BitFrom; } return false; } /// /// Implements the operator >=. /// /// The object1. /// The object2. /// /// Returns value. /// public static bool operator >=(BitRange object1, BitRange object2) { if (object1 != null && object2 != null) { return object1.BitFrom >= object2.BitFrom; } return false; } #endregion #region Public methods /// Makes a deep copy of the BitRange object. /// Returns object. public object Clone() { return new BitRange(this.Order, this.BitFrom, this.Length); } #endregion #region Serialization /// /// Sets Xml representation. /// /// Xml Element. public void SetXElement(XElement element) { Contract.Requires(element != null); //// if (element == null) { return; } this.Order = XmlSupport.ReadByteAttribute(element.Attribute("Order")); this.BitFrom = XmlSupport.ReadByteAttribute(element.Attribute("Start")); this.Length = XmlSupport.ReadByteAttribute(element.Attribute("Length")); } #endregion #region Comparison /// Support for potential comparing of bit ranges. /// Object to be compared. /// Returns value. public int CompareTo(object obj) { return obj is BitRange br ? this.BitFrom.CompareTo(br.BitFrom) : 0; //// This kills the DataGrid //// throw new ArgumentException("Object is not a BitRange"); } /// Test of equality. /// Object to be compared. /// Returns value. public override bool Equals(object obj) { //// check null (this pointer is never null in C# methods) if (object.ReferenceEquals(obj, null)) { return false; } if (object.ReferenceEquals(this, obj)) { return true; } if (this.GetType() != obj.GetType()) { return false; } return this.CompareTo(obj) == 0; } /// Support of comparison. /// Returns value. public override int GetHashCode() { return this.BitFrom.GetHashCode(); } #endregion #region Operations /// Returns intersection with the given Range. /// Given range. /// Resulting range. public bool Intersect(BitRange range) { if (range == null) { return false; } var b1 = Math.Max(range.BitFrom, this.BitFrom); var b2 = Math.Min(range.BitTo, this.BitTo); return b1 <= b2; } /// Returns intersection with the given Range. /// Given range. /// Resulting range. public BitRange IntersectionWith(BitRange range) { if (range == null) { return null; } var b1 = Math.Max(range.BitFrom, this.BitFrom); var b2 = Math.Min(range.BitTo, this.BitTo); var br = b1 <= b2 ? new BitRange(this.Order, b1, (byte)(b2 - b1 + 1)) : new BitRange(this.Order, 0, 0); return br; } /// /// Bit to stops at. /// /// The bit stop. /// Returns value. public BitRange StopAt(byte bitStop) { var b1 = this.BitFrom; var b2 = Math.Min(bitStop, this.BitTo); var br = b1 <= b2 ? new BitRange(this.Order, b1, (byte)(b2 - b1 + 1)) : new BitRange(this.Order, 0, 0); return br; } /// Gets a value indicating whether the range contains the given bit. /// Given bit. /// Logical value. public bool ContainsBit(byte givenBit) { return (this.BitFrom <= givenBit) && (givenBit <= this.BitTo); } /// Checks if the Range Contains the given range. /// Given range. /// Logical value. public bool CoverRange(BitRange range) { if (range == null) { return false; } return (this.BitFrom <= range.BitFrom) && (range.BitTo <= this.BitTo); } #endregion #region String representation /// String representation of the object. /// Returns value. public override string ToString() { var s = new StringBuilder(); s.Append(this.BitFrom.ToString("D", CultureInfo.CurrentCulture.NumberFormat)); s.Append("-"); s.Append(this.BitTo.ToString("D", CultureInfo.CurrentCulture.NumberFormat)); s.Append("("); s.Append(this.Length.ToString("D", CultureInfo.CurrentCulture.NumberFormat)); s.Append(")"); return s.ToString(); } #endregion } }